/*
 * Copyright (c) 2024 iSoftStone Education Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <stdio.h>
#include "los_task.h"
#include "ohos_init.h"
#include "sht30.h"
#include "iot_errno.h"
#include "iot_gpio.h"
#include "picture.h"
#include "lcd.h"

// 新增显示相关定义
#define DISPLAY_REFRESH_INTERVAL 1000  // 显示刷新间隔(ms)
#define TEXT_COLOR LCD_WHITE          // 文字颜色
#define BG_COLOR LCD_BLACK            // 背景颜色
#define TEXT_SIZE 24                  // 文字大小

extern float g_humi;
extern float g_temp;

/* GPIO定义 */
#define GPIO_BODY_INDUCTION      GPIO0_PA3  // 人体感应传感器
#define GPIO_LED                 GPIO0_PA5  // LED灯

/* 全局变量 */
static volatile uint8_t g_human_detected = 0;  // 人体检测标志
static volatile uint8_t g_led_state = 0;       // LED状态
static unsigned int g_no_detection_count = 0;  // 无人体检测计数

/***************************************************************
* 函数名称: gpio_isr_func
* 说    明: 人体感应中断处理函数
* 参    数: 无
* 返 回 值: 无
***************************************************************/
void gpio_isr_func(void *args)
{
    printf("Human detected!\n");
    g_human_detected = 1;          // 设置人体检测标志
    g_no_detection_count = 0;      // 重置无人体计数
    
    // 立即点亮LED
    IoTGpioSetOutputVal(GPIO_LED, IOT_GPIO_VALUE1);
    g_led_state = 1;
}

/***************************************************************
* 函数名称: led_control_task
* 说    明: LED控制任务
* 参    数: 无
* 返 回 值: 无
***************************************************************/
void led_control_task()
{
    // 初始化LED GPIO
    IoTGpioInit(GPIO_LED);
    IoTGpioSetDir(GPIO_LED, IOT_GPIO_DIR_OUT);

    
    while (1) {
        if (g_human_detected) {
            // 人体检测模式下，LED保持常亮
            if (!g_led_state) {
                IoTGpioSetOutputVal(GPIO_LED, IOT_GPIO_VALUE1);
                g_led_state = 1;
            }
            
            // 检查是否连续10秒无人体活动
            if (g_no_detection_count >= 10) {
                g_human_detected = 0;
                g_no_detection_count = 0;
                printf("No human detected for 10s, return to blinking mode\n");
            }
        } else {
            // 正常模式下，LED0.5秒闪烁
            g_led_state = !g_led_state;
            IoTGpioSetOutputVal(GPIO_LED, g_led_state);
        }
        
        LOS_Msleep(500);  // 500ms控制周期
    }
}

/***************************************************************
* 函数名称: human_check_task
* 说    明: 人体检测状态维护任务
* 参    数: 无
* 返 回 值: 无
***************************************************************/
void human_check_task()
{
    // 初始化人体感应传感器GPIO
    IoTGpioInit(GPIO_BODY_INDUCTION);
    IoTGpioSetDir(GPIO_BODY_INDUCTION, IOT_GPIO_DIR_IN);
    
    // 设置中断(上升沿触发)
    int ret = IoTGpioRegisterIsrFunc(GPIO_BODY_INDUCTION, 
                    IOT_INT_TYPE_EDGE, 
                    IOT_GPIO_EDGE_RISE_LEVEL_HIGH, 
                    gpio_isr_func, NULL);
    if (ret != IOT_SUCCESS) {
        printf("Failed to register ISR: %d\n", ret);
        return;
    }
    IoTGpioSetIsrMask(GPIO_BODY_INDUCTION, FALSE);  // 启用中断
    
    while (1) {
        printf("Human detection status: %s\n", 
              g_human_detected ? "Detected" : "Not detected");
        
        // 如果当前是检测状态，每秒增加无检测计数
        if (g_human_detected) {
            g_no_detection_count++;
        }
        
        LOS_Msleep(1000);  // 每秒检查一次
    }
}

/***************************************************************
 * 函数名称: sht30_proress
 * 说    明: sht30实验
 * 参    数: 无
 * 返 回 值: 无
 ***************************************************************/
void sht30_proress(void *arg)
{
    double sht30_data[2] = {0};

    /* 初始化sht30 */
    sht30_init();

    while (1)
    {
        printf("************ Sht30 Process ************\n");

        /* 读取sht30数据 */
        sht30_read_data(sht30_data);

        printf("temperature %.2f RH %.2f \r\n", sht30_data[0], sht30_data[1]);

        g_temp = sht30_data[0];
        g_humi = sht30_data[1];

        printf("\r\n");

        LOS_Msleep(1000);
    }
}

/***************************************************************
 * 函数名称: display_task
 * 说    明: 显示任务，在LCD上显示环境信息
 * 参    数: 无
 * 返 回 值: 无
 ***************************************************************/
void display_task(void *arg)
{
    // 初始化LCD
    lcd_init();
    // 清屏
    lcd_fill(0, 0, LCD_W, LCD_H, BG_COLOR);
    
    char temp_str[20];
    char humi_str[20];
    char human_str[30];
    
    while (1) {
        // 格式化显示内容
        snprintf(temp_str, sizeof(temp_str), "Temp: %.1fC", g_temp);
        snprintf(humi_str, sizeof(humi_str), "Humi: %.1f%%", g_humi);
        snprintf(human_str, sizeof(human_str), "Human: %s", 
                 g_human_detected ? "Detected" : "Not Detected");
        
        // 显示温度
        lcd_show_string(20, 50, (uint8_t *)temp_str, TEXT_COLOR, BG_COLOR, TEXT_SIZE, 0);
        // 显示湿度
        lcd_show_string(20, 100, (uint8_t *)humi_str, TEXT_COLOR, BG_COLOR, TEXT_SIZE, 0);
        // 显示人体检测状态
        lcd_show_string(20, 150, (uint8_t *)human_str, TEXT_COLOR, BG_COLOR, TEXT_SIZE, 0);
        
        // 显示标题
        lcd_show_string(50, 10, (uint8_t *)"Env Monitor", LCD_YELLOW, BG_COLOR, 32, 0);
        
        LOS_Msleep(DISPLAY_REFRESH_INTERVAL);
    }
}

/***************************************************************
 * 函数名称: sht30_example
 * 说    明: 开机自启动调用函数
 * 参    数: 无
 * 返 回 值: 无
 ***************************************************************/
void sht30_example()
{
   unsigned int thread_id, led_task_id, human_task_id, display_task_id;
    TSK_INIT_PARAM_S task = {0}, led_task = {0}, human_task = {0}, display_task_param = {0};
    unsigned int ret = LOS_OK;

    // 1. 创建SHT30温湿度检测任务
    task.pfnTaskEntry = (TSK_ENTRY_FUNC)sht30_proress;
    task.uwStackSize = 2048;
    task.pcName = "sht30 process";
    task.usTaskPrio = 23;
    ret = LOS_TaskCreate(&thread_id, &task);
    if (ret != LOS_OK) {
        printf("Failed to create SHT30 task:0x%x\n", ret);
    }

    // 2. 创建LED控制任务
    led_task.pfnTaskEntry = (TSK_ENTRY_FUNC)led_control_task;
    led_task.uwStackSize = 2048;
    led_task.pcName = "LED Control Task";
    led_task.usTaskPrio = 25;
    ret = LOS_TaskCreate(&led_task_id, &led_task);
    if (ret != LOS_OK) {
        printf("Failed to create LED task: 0x%x\n", ret);
    }
    
    // 3. 创建人体检测任务
    human_task.pfnTaskEntry = (TSK_ENTRY_FUNC)human_check_task;
    human_task.uwStackSize = 2048;
    human_task.pcName = "Human Detect Task";
    human_task.usTaskPrio = 24;
    ret = LOS_TaskCreate(&human_task_id, &human_task);
    if (ret != LOS_OK) {
        printf("Failed to create human detect task: 0x%x\n", ret);
    }
    
    // 4. 新增显示任务
    display_task_param.pfnTaskEntry = (TSK_ENTRY_FUNC)display_task;
    display_task_param.uwStackSize = 2048;
    display_task_param.pcName = "Display Task";
    display_task_param.usTaskPrio = 22;  // 较低优先级
    ret = LOS_TaskCreate(&display_task_id, &display_task_param);
    if (ret != LOS_OK) {
        printf("Failed to create display task: 0x%x\n", ret);
    }
}

APP_FEATURE_INIT(sht30_example);
